package com.yazi.mxz.gather.main.goods;

import java.io.IOException;
import java.math.BigDecimal;
import java.net.SocketException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;



import org.apache.http.HttpResponse;
import org.apache.http.ParseException;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.nio.client.CloseableHttpAsyncClient;
import org.apache.http.impl.nio.client.HttpAsyncClients;
import org.apache.http.util.EntityUtils;

import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.dataformat.xml.XmlMapper;
import com.yazi.mxz.gather.common.App;
import com.yazi.mxz.gather.common.App.PicObject;
import com.yazi.mxz.gather.entity.enums.ProcessType;
import com.yazi.mxz.gather.entity.http.YjgxcsResBody4Cat;
import com.yazi.mxz.gather.entity.http.YjgxcsResBody4Detail;
import com.yazi.mxz.gather.entity.http.YjgxcsResBody4List;
import com.yazi.mxz.gather.entity.http.YjgxcsResBody4Cat.Span;
import com.yazi.mxz.gather.entity.http.YjgxcsResBody4Detail.Li;
import com.yazi.mxz.gather.entity.http.YjgxcsResBody4List.Td;
import com.yazi.mxz.gather.entity.http.YjgxcsResBody4List.Tr;
import com.yazi.mxz.gather.entity.repository.ProcessLog;
import com.yazi.mxz.gather.entity.repository.Product;
import com.yazi.mxz.gather.repository.ProcessLogRepository;
import com.yazi.mxz.gather.repository.ProductRepository;

/**
 * 永嘉供销超市
 * http://www.yjgxcs.com
 * @author mo_yq5
 * @date 2015-8-11
 */
public class YjgxcsCom extends Thread {
	
	private CloseableHttpAsyncClient httpclient;
	private ProcessLogRepository logRepository;
	private ProductRepository productRepository;
	private ObjectMapper om;
	
	public Long start;
	
	public YjgxcsCom() {
		init();
	}
	
	public YjgxcsCom(int startPage, int endPage) {
		init();
		ProcessLog log = logRepository.findOne(ProcessType.YJGXCS.ordinal());
		if (null == log) {
			log = new ProcessLog();
			log.setId(ProcessType.YJGXCS.ordinal());
			log.setCur((long)startPage);
			log.setEnd((long)endPage);
			log.setCount(0);
			logRepository.insert(log);
		} else {
			log.setCur((long)startPage);
			log.setEnd((long)endPage);
			logRepository.save(log);
		}
	}
	
	public void init() {
		
		logRepository = App.context.getBean(ProcessLogRepository.class);
		productRepository = App.context.getBean(ProductRepository.class);
		
		httpclient = HttpAsyncClients.createDefault();
		httpclient.start();
		
		om = new XmlMapper();
		om.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
	}

	@Override
	public void run() {
		
		ProcessLog log = logRepository.findOne(ProcessType.YJGXCS.ordinal());
		if (null == log) {
			System.out.println(ProcessType.YJGXCS + "日志不存在");
			return;
		}
		boolean isContinue = false;
		
		try {
			
			
			while (true) {
				
				if (log.getCur() > log.getEnd()) {
					isContinue = false;
					break;
				}
				
				barcodeInfo(log.getCur());
				
				log.setCur(log.getCur() + 1);// 从大到小
				logRepository.save(log);
			
				sleep(200);
			}
			
		} catch (SocketException e) {
			e.printStackTrace();
			isContinue = true;
			
		} catch (Exception e1) {
			e1.printStackTrace();
			
		} 
		if (isContinue) {
			run();
		} else {
			System.out.println("执行结束！");
		}
	}
	
	private String barcodeInfo(long pageNum) throws JsonParseException, JsonMappingException,
			IOException, InterruptedException, ExecutionException {
		
		System.out.println("PageNum:" + pageNum);
		
		final HttpGet req = new HttpGet("http://yjgxcs.com/?gallery---2--" + pageNum + "--grid.html");
		Future<HttpResponse> future = httpclient.execute(req, null);
		HttpResponse res = future.get();
		
		System.out.println(req.getRequestLine() + "->" + res.getStatusLine());
		
		String body = EntityUtils.toString(res.getEntity(), "utf-8");
		if (body.isEmpty()) {
			System.out.println("无响应内容!");
			return null;
		}
		
		//<table width="100%" border="0" cellpadding="0" cellspacing="0" class='grid'> <tbody>
		//</tbody> </table> <script>
		int startIndex = body.indexOf("<table width=\"100%\" border=\"0\" cellpadding=\"0\" cellspacing=\"0\" class='grid'> <tbody>");
		int endIndex = body.indexOf("</table> <script>") + 8;
		body = body.substring(startIndex, endIndex);
		
		// 修改正源标签错误
		body = body.replaceAll("</li>  </li>", "</li>")// 标签起止标签不匹配
				.replaceAll("</tr>  </tr>", "</tr>") // 标签起止标签不匹配
				.replaceAll("title=\"查看详细\"", "") // 一个标签中重复相同属性
				.replaceAll("<td colspan=\"3\">&nbsp;</td>", "")
				.replaceAll("&nbsp;", "")
				.replaceAll("&amp;", "")
				.replaceAll("&", "");
		
		//System.out.println(body);
		
		YjgxcsResBody4List yjgxcs4List = om.readValue(body, YjgxcsResBody4List.class);
		List<Tr> trs = yjgxcs4List.getTbody().getTrs();
		StringBuffer goodsInfo = new StringBuffer();
		String proId, name, barcode, pic, price, catName, spec, unit, bigPic, mkPrice;
		for (Tr tr : trs) {
			List<Td> tds = tr.getTds(); // 每行中的商品td
			
			for (Td td : tds) {
				
				proId = td.getProduct();// (站点)商品ID
				// 可能是列表中最后补空的
				if (null == proId) {
					continue;
				}
				
				Map<String, String> detail = getDetailInfo(proId);
				
				if (!App.checkBarCode(detail.get("barcode"))) {
					System.out.println("商品无条码: " + proId + " -> " + detail.get("name"));
					continue;
				}
				
				barcode = detail.get("barcode");
				name = detail.get("name");
				catName = detail.get("catName");
				unit = detail.get("unit");
				spec = detail.get("spec");
				price = detail.get("price");
				mkPrice = detail.get("mkPrice");
				pic = detail.get("pic");
				bigPic = detail.get("bigPic");
				
				goodsInfo = new StringBuffer();
				goodsInfo.append("\r\nID:" + proId);
				goodsInfo.append("\r\n名称:" + name);
				goodsInfo.append("\r\n单位:" + unit);
				goodsInfo.append("\r\n单价:" + price);
				goodsInfo.append("\r\n市场价:" + mkPrice);
				goodsInfo.append("\r\n分类:" + catName);
				goodsInfo.append("\r\n规格:" + spec);
				goodsInfo.append("\r\n小图:" + pic);
				goodsInfo.append("\r\n大图:" + bigPic);
				System.out.println(goodsInfo);
				
				App.PicObject picObj = new App.PicObject();
				if (null != pic ) {
					App.setPic(pic, picObj);
				}
				if (null != bigPic) {
					App.setPic(bigPic, picObj);
				}
				
				if (!productRepository.exists(barcode)) {
					
					System.out.println("添加: " + barcode + " -> " + name);
					
					Product product = new Product();

					//product.setArea(items.getCountry());
					product.setBarcode(barcode);
					product.setBigPic(App.saveGoodsBigImageV1(picObj.getBigPic()));
					//product.setBrandName(brandName);
					product.setCatName(catName);
					//product.setFacCode(items.getFacCode());
					//product.setFacName(items.getFacName());
					product.setIsCheckName(true);
					product.setMidPic(App.saveGoodsMiddleImageV1(picObj.getMidPic()));
					product.setName(name);
					//product.setSpell(rs.getString("pinyin"));
					product.setPic(App.saveGoodsImageV1(picObj.getPic()));
					product.setPrice(price);
					product.setUnit(unit);
					product.setSource("yjgxcs.com");
					product.setSpec(spec);
					//product.setSupplier(items.getSupplier());
					product.setSysRemark(proId);

					productRepository.insert(product);

				} else {
					
					System.out.println("修改: " + barcode + " -> " + name);

					Product product = productRepository.findOne(barcode);
					
					// 本站都是无水印图片,可直接覆盖现有图片
					if (null != picObj.getBigPic() && null != (pic = (App.saveGoodsBigImageV1(picObj.getBigPic())))) {
						App.delGoodsImageV1(product.getBigPic());
						product.setBigPic(pic);
					}
					if (null != picObj.getMidPic() && null != (pic = (App.saveGoodsMiddleImageV1(picObj.getMidPic())))) {
						App.delGoodsImageV1(product.getMidPic());
						product.setMidPic(pic);
					}
					if (null != picObj.getPic() && null != (pic = (App.saveGoodsImageV1(picObj.getPic())))) {
						App.delGoodsImageV1(product.getPic());
						product.setPic(pic);
					}
					
					if (null != catName) {//  && null == product.getCatName()
						product.setCatName(catName);
					}
					if (null != name) {// && null == product.getName()
						product.setName(name);
					}
					if (null != price) {// && null == product.getPrice()
						product.setPrice(price);
					}
					if (null != unit) {// && null == product.getUnit()
						product.setUnit(unit);
					}
					if (null != spec) {// && null == product.getSpec()
						product.setSpec(spec);
					}
					
					productRepository.save(product);

				}
			}
			
		}
		
		return null;
	}
	
	private Map<String, String> getDetailInfo(String proId) throws InterruptedException, ExecutionException, ParseException, IOException {

		final HttpGet req = new HttpGet("http://www.yjgxcs.com/product-"+ proId +".html");
		Future<HttpResponse> future = httpclient.execute(req, null);
		HttpResponse res = future.get();
		
		System.out.println(req.getRequestLine() + "->" + res.getStatusLine());
		
		StringBuffer bodySb = new StringBuffer(EntityUtils.toString(res.getEntity(), "utf-8"));
		if (bodySb.length() == 0) {
			System.out.println("无响应内容!");
			return null;
		}
		
		// 分类相关
		int startIndex = bodySb.indexOf("<div class=\"Navigation\">");
		int endIndex = bodySb.indexOf("</div></div> <style>");
		if (endIndex == -1) {
			endIndex = bodySb.indexOf("</div></div> <script>");
		}
		String catStr = bodySb.substring(startIndex, endIndex);
		catStr =  catStr
				.replaceAll("<span>&raquo;</span></td>", "")
				.replaceAll("&nbsp;", "");
		//.replaceAll("您当前的位置： ", "");
		
		YjgxcsResBody4Cat yjgxcs4Cat = om.readValue(catStr, YjgxcsResBody4Cat.class);
		List<Span> spans = yjgxcs4Cat.getSpans();
		spans.remove(0);// 删除"首页"
		String catName = "";
		for (Span span : spans) {
			catName += (catName.isEmpty() ? "":",") +  span.getA().getText();// 各级分类间用,号
		}
		
		// 其它详情
		startIndex = bodySb.indexOf("<table width=\"100%\">");// <table width="100%">
		endIndex = bodySb.indexOf("<form id='fastbuy-form'") - 18;// </table> <!--立即购买FROM-->  <form id='fastbuy-form' 
		StringBuffer detailSb =  new StringBuffer(bodySb.substring(startIndex, endIndex));
		
		// <li><span>商品重量：</span><span>72.000</span> 克(g)</li> 如增加个span包住'克(g)'
		String str = "<li><span>商品重量：</span>";
		startIndex = detailSb.indexOf(str);
		if (startIndex > -1) {
			endIndex = detailSb.indexOf("</span>", startIndex + str.length());
			detailSb.insert(endIndex + 7, "<span>");
			endIndex = detailSb.indexOf("</li>", endIndex);
			detailSb.insert(endIndex, "</span>");
		}
		// <li><span>计量单位：</span>杯</li> 如增加个span包住'杯'
		str = "<li><span>计量单位：</span>";
		startIndex = detailSb.indexOf(str);
		if (startIndex > -1) {
			detailSb.insert(startIndex + str.length(), "<span>");
			endIndex = detailSb.indexOf("</li>", startIndex + str.length());
			detailSb.insert(endIndex, "</span>");
		}
		// <li><span>所得积分：</span><span id="goodsScore">1</span> 补</li>(源代码缺失问题)
		str = "<li><span>所得积分：</span>";
		startIndex = detailSb.indexOf(str);
		if (startIndex > -1) {
			endIndex = detailSb.indexOf("</ul>", startIndex + str.length());
			detailSb.insert(endIndex, "</li>");
		}
		
		String detailStr = detailSb.toString()
				.replaceAll("<div class='hightline'>[\\s|\\S]*</div>", "")// 去掉大而没用的块
				.replaceAll("<script>[\\s|\\S]*</script>", "")// 去除脚本
				.replaceAll("</i> </span>", "</i>")// 修正结构错误
				.replaceAll("&nbsp;", "")
				.replaceAll("&amp;", "")
				.replaceAll("&", "");
		
		// 去除注释<!-- -->
		String subString;// 注释内容
		while(true) {
			startIndex = detailStr.indexOf("<!--");
			if (startIndex == -1) {
				break;
			} 
			subString = detailStr.substring(startIndex, detailStr.indexOf("-->", startIndex) + 3);
			detailStr = detailStr.replace(subString, "");
		}
		
		//System.out.println(detailStr);
		YjgxcsResBody4Detail yjgxcs4Detail = om.readValue(detailStr, YjgxcsResBody4Detail.class);
		
		String bigPic = null, pic = null, name = null, spec = null, barcode = null, unit = null, price = null, mkPrice = null;
		
		bigPic = yjgxcs4Detail.getTr().getTds().get(0).getDiv().getDiv().getBigpicsrc();// 大图
		pic = yjgxcs4Detail.getTr().getTds().get(0).getDiv().getDiv().getA().getImg().getSrc();// 小图
		name = yjgxcs4Detail.getTr().getTds().get(1).getForm().getH1().getText();//名称
		
		// 默认每个商品的属性类型不确定
		List<Li> liList = yjgxcs4Detail.getTr().getTds().get(1).getForm().getUls().get(0).getLis();
		List<com.yazi.mxz.gather.entity.http.YjgxcsResBody4Detail.Span> spanList;
		for (Li li : liList) {
			spanList = li.getSpans();
			if (spanList.get(0).getText().equals("商品重量：")) {// 规格
				spec = spanList.get(1).getText().trim();
				spec = "" + new BigDecimal(spec).setScale(0,BigDecimal.ROUND_DOWN);// 25.000克　去0
				spec +=spanList.get(2).getText().trim();
			} else if (spanList.get(0).getText().equals("货号：")) {// 条码
				barcode = spanList.get(1).getText().trim();
			} else if (spanList.get(0).getText().equals("计量单位：")) {// 单位
				unit = spanList.get(1).getText().trim();
			} 
		}
		
		liList = yjgxcs4Detail.getTr().getTds().get(1).getForm().getUls().get(1).getLis();
		price = liList.get(0).getI().getText().replaceAll("￥", "");// 售价
		mkPrice = liList.get(1).getSpans().get(1).getText().replaceAll("￥", "");// 市场价
		
		Map<String, String> detail = new HashMap<String, String>();
		detail.put("barcode", barcode);
		detail.put("name", name);
		detail.put("catName", catName);
		detail.put("unit", unit);
		detail.put("spec", spec);
		detail.put("price", price);
		detail.put("mkPrice", mkPrice);
		detail.put("pic", pic);
		detail.put("bigPic", bigPic);
		return detail;
	}
	
}
